//
//  HTTPDownloader.m
//  qw-troad-ios
//
//  Created by Yunhai.Wu on 15/8/14.
//  Copyright (c) 2015年 117go. All rights reserved.
//

#import "QWHTTPDownloader.h"
#import "IQWHTTPDownloadCache.h"

/**
 *  http 下载器超时时间
 */
#define DEFAULT_HTTP_DOWNLOAD_TIME_OUT_INTERVAL 100

NSString *const QWHTTPDownloaderCancelAllNotification = @"QWHTTPDownloaderCancelAllNotification";

@interface QWHTTPDownloader ()<NSURLConnectionDataDelegate>
@property (nonatomic, copy) QWDownloadFinishBlock finishBlock;
@property (nonatomic, copy) QWDownloadProgressBlock progressBlock;
@property (nonatomic, copy) QWDownloadFailBlock errorBlock;
@property (nonatomic, copy) NSString *downloadURL;
@property (nonatomic, strong) NSURLConnection *connection;
@property (nonatomic, strong) NSMutableData *responseData;
@property (nonatomic, strong) NSURLResponse *response;
@end

@implementation QWHTTPDownloader

-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
    [self.responseData appendData:data];
    if (self.progressBlock != NULL) {
        double receDataLength = (double)[self.responseData length];
        double totalLength = (double)[self.response expectedContentLength];
        self.progressBlock(receDataLength/totalLength);
    }
}
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
    self.responseData = [[NSMutableData alloc] init];
    self.response = response;
    if (self.progressBlock != NULL) {
        self.progressBlock(0.0f);
    }
}
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
    if (self.errorBlock != NULL) {
        self.errorBlock(error);
    }
    self.response = nil;
    self.responseData = nil;
}
-(void)connectionDidFinishLoading:(NSURLConnection *)connection {
    if (self.progressBlock != NULL) {
        self.progressBlock(1.0f);
    }
    if (self.finishBlock != NULL) {
        self.finishBlock([[NSData alloc] initWithData:self.responseData]);
    }
    if (_cache && [self.responseData length] > 0) {
        [[[QWHTTPDownloaderConfig sharedInstance] cache] cacheData:self.responseData forKey:self.downloadURL cacheDuration:[[QWHTTPDownloaderConfig sharedInstance] defaultCacheDuration]];
    }
    self.responseData = NULL;
    self.response = NULL;
    self.errorBlock = NULL;
    self.finishBlock = NULL;
    self.progressBlock = NULL;
}

-(void)cancel {
    if (_connection && _downloading) {
        [_connection cancel];
        _downloading = NO;
    }
}

-(void)asynDownload:(NSString *)url finish:(QWDownloadFinishBlock)finishBlock error:(QWDownloadFailBlock)errorBlock progress:(QWDownloadProgressBlock)progressBlock cache:(BOOL)cache {
    if (!_downloading) {
        if (![url isEqualToString:@""]) {
            self.finishBlock = finishBlock;
            self.errorBlock = errorBlock;
            self.progressBlock = progressBlock;
            _cache = cache;
            self.downloadURL = url;
            if (_cache) {
                id<IQWHTTPDownloadCache> downloadCache = [[QWHTTPDownloaderConfig sharedInstance] cache];
                if ([downloadCache hasCacheKey:url]) {
                    NSData *data = [downloadCache getCacheDataForKey:url];
                    if (self.finishBlock != NULL) {
                        self.finishBlock(data);
                        return;
                    }
                }
            }
            self.connection = [[NSURLConnection alloc] initWithRequest:[[NSURLRequest alloc] initWithURL:[NSURL URLWithString:url] cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:_timeoutInterval] delegate:self startImmediately:YES];
            _downloading = YES;
        } else {
            if (_errorBlock != NULL) {
                _errorBlock([NSError errorWithDomain:@"HTTPDownloader 02" code:0 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"url empty ...",NSLocalizedDescriptionKey, nil]]);
            }
        }
    } else {
        if (_errorBlock != NULL) {
            _errorBlock([NSError errorWithDomain:@"HTTPDownloader 01" code:0 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"downloading ...",NSLocalizedDescriptionKey, nil]]);
        }
    }
}

-(void)syncDownload:(NSString *)url finish:(QWDownloadFinishBlock)finishBlock error:(QWDownloadFailBlock)errorBlock cache:(BOOL)cache {
    if (![url isEqualToString:@""]) {
        if (cache) {
            id<IQWHTTPDownloadCache> downloadCache = [[QWHTTPDownloaderConfig sharedInstance] cache];
            if ([downloadCache hasCacheKey:url]) {
                NSData *data = [downloadCache getCacheDataForKey:url];
                if (finishBlock != NULL) {
                    finishBlock(data);
                    return;
                }
            }
        }
        NSHTTPURLResponse *response = nil;
        NSError *error = nil;
        NSData *data = [NSURLConnection sendSynchronousRequest:[[NSURLRequest alloc] initWithURL:[NSURL URLWithString:url]] returningResponse:&response error:&error];
        if ([response statusCode] == 200 && [data length] > 0) {
            finishBlock(data);
        } else {
            errorBlock(error);
        }
    } else {
        if (errorBlock != NULL) {
            errorBlock([NSError errorWithDomain:@"HTTPDownloader 02" code:0 userInfo:[NSDictionary dictionaryWithObjectsAndKeys:@"url empty ...",NSLocalizedDescriptionKey, nil]]);
        }
    }
}

-(id)init {
    self = [super init];
    if (self) {
        _cache = YES;
        _timeoutInterval = DEFAULT_HTTP_DOWNLOAD_TIME_OUT_INTERVAL;
        //注册通知
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(cancel) name:QWHTTPDownloaderCancelAllNotification object:nil];
    }
    return self;
}
-(void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}
+(void)cancelAll {
    [[NSNotificationCenter defaultCenter] postNotificationName:QWHTTPDownloaderCancelAllNotification object:nil];
}
+(instancetype)instance {
    QWHTTPDownloader *instance = [[QWHTTPDownloader alloc] init];
    return instance;
}
@end